package org.game.quartz;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.cfg.DungeonLevelGroupCfg;
import org.cfg.cache.DungeonLevelGroupCfgCache;
import org.constant.EventConditionKey;
import org.constant.EventConditionType;
import org.constant.EventType;
import org.game.cache.OnlinePlayerCache;
import org.game.cache.ServerCache;
import org.game.constant.DungeonConstant;
import org.game.db.bean.DungeonLevel;
import org.game.db.bean.DungeonLevelGroup;
import org.game.db.bean.Player;
import org.game.db.cache.DungeonLevelCache;
import org.game.db.cache.DungeonLevelGroupCache;
import org.game.manager.*;
import org.game.module.datingbo.trigger.CityDatingTriggerManager;
import org.game.module.dungeonbo.DungeonBO;
import org.game.msgBuilder.DungeonMsgBuilder;
import org.game.msgBuilder.TaskMsgBuilder;
import org.game.plugin.event.GameEvent;
import org.game.plugin.event.GameEventPlugin;
import org.game.protobuf.s2c.S2CDungeonMsg;
import org.game.protobuf.s2c.S2CShareMsg.ChangeType;
import org.game.protobuf.s2c.S2CTaskMsg.TaskInfo;
import org.game.util.ProtoUnit;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.utils.TimeUtil;
import org.utils.timeframe.TimeFrameChecker;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sojoys.artifact.manager.MessageManager;
import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.log.Log;
import com.xiaoleilu.hutool.log.LogFactory;

/**
 * Created by fxf on 2017/9/15.
 */
public class MinuteJob implements Job {

    static final Log log = LogFactory.get(MinuteJob.class);
    
    // 最后一次执行时间
    static Date LAST_EXECUTE_DATE = new Date();
    
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
    	Date nowDate = new Date();
        try {
        	// 是否跨天
        	boolean isNewDay = DateUtil.betweenDay(LAST_EXECUTE_DATE, ServerCache.newDate, true) > 0;
        	
        	GameServerManager.me().registerGameServerInfo();
        	
            Collection<Player> players = OnlinePlayerCache.getAll();

            int todayMinute = TimeUtil.getTodayTimeMinute();

//            refreshShop(players, todayMinute);

            noticeActivityDungeonTimePoint(players, nowDate);

            refreshDungeon(players,isNewDay);
            // 检查任务
            checkTasks(players);

            //检查每日任务（登录）
            checkDayTask(players, nowDate, isNewDay);
            
            // 执行下线玩家缓存清理
            OnlinePlayerCache.clearPlayerCache();

            //刷新充值礼包购买记录
            refreshRechargeRecord(players, isNewDay);
            
            //检查无尽回廊阶段变化
            EndlessCloisterManager.me().checkStepUpdate(nowDate);

            refreshCityDating(players, nowDate, isNewDay);
        } catch (Exception e) {
            log.error(e);
        }
        LAST_EXECUTE_DATE = nowDate;
    }

    private void checkDayTask(Collection<Player> players, Date nowDate, boolean isNewDay) {
    	if (isNewDay) {
    		for (Player player : players) {
                Date lastLoginDate = player.getLastLoginTime();
                // 触发跨天登陆事件
                Map<String, Object> in = Maps.newHashMap();
                in.put(EventConditionKey.LAST_LOGIN_DATE, lastLoginDate);
                in.put(EventConditionKey.NOW_LOGIN_DATE, nowDate);
                GameEvent event = new GameEvent(player, EventType.LOGIN, in);
                GameEventPlugin.syncSubmit(event);

                // 触发月卡激活事件
                in = Maps.newHashMap();
                in.put(EventConditionKey.CONDITION_TYPE, EventConditionType.GAIN_MONTH_CARD);
                event = new GameEvent(player, EventType.OTHER_EVENT, in);
                GameEventPlugin.syncSubmit(event);
                
                // 重置最后登录时间
                player.setLastLoginTime(nowDate);
                
                // 重置玩家数据
                PlayerManager.me().resetPlayerData(player);
            }
		}
    }

    /**
     * 任务检查
     * @param players
     */
    private void checkTasks(Collection<Player> players){
    	List<TaskInfo> taskInfos = Lists.newArrayList();
    	for (Player player : players) {
    		// 过期任务
    		taskInfos.addAll(TaskMsgBuilder.createTaskInfoList(player, ChangeType.DELETE, TaskManager.me().checkTimeOutTasks(player)));
    		// 重置任务
    		taskInfos.addAll(TaskMsgBuilder.createTaskInfoList(player, ChangeType.UPDATE, TaskManager.me().resetTasks(player)));
    		if (!taskInfos.isEmpty()) {
        		TaskManager.me().notifyTaskInfos(player, taskInfos);
			}
    		taskInfos.clear();
		}
    }
    
    

    private void refreshDungeon(Collection<Player> players, boolean isNewDay) {
        if (isNewDay) {
        	long now = System.currentTimeMillis();
            players.forEach(player -> {
                List<DungeonLevelGroup> groupList = DungeonLevelGroupCache.me().getByPlayerId(player.getId());
                List<DungeonLevelGroup> refreshGroupList = Lists.newArrayList();
                groupList.forEach(group -> {
                    if (group.getDungeonLevelGroupProxy().getCfg().getCycleType() == DungeonConstant.FIGHT_COUNT_REFRESH_TYPE_DAILY) {
                        group.getDungeonLevelGroupProxy().refreshCount(now);
                        refreshGroupList.add(group);
                    }
                });
                player.getPlayerProxy().sendMsg(MessageManager.me().create(DungeonBO.refreshLevelGroupCount, ProtoUnit.toByte(DungeonMsgBuilder.getDungeonLevelGroupList(refreshGroupList))));
                List<DungeonLevel> levelList = DungeonLevelCache.me().getByPlayerId(player.getId());
                List<DungeonLevel> refreshLevelList = Lists.newArrayList();
                levelList.forEach(level->{
                   boolean refreshed = level.getDungeonLevelProxy().refreshFightCount(now);
                    if (refreshed){
                        refreshLevelList.add(level);
                    }
                });
                player.getPlayerProxy().sendMsg(MessageManager.me().create(DungeonBO.updateLevelInfo, ProtoUnit.toByte(DungeonMsgBuilder.getLevelInfoList(refreshLevelList))));
            });
        }
    }

    /**
     * 通知活动副本开启及结束
     */
    private void noticeActivityDungeonTimePoint(Collection<Player> players,Date date){
        Map<Integer,List<Integer>> timePointGroups = getTimePointGroup(date);
        if (timePointGroups.size() > 0){
            S2CDungeonMsg.UpdateActivityDungeon msg = DungeonMsgBuilder.getUpdateActivityDungeonMsg(timePointGroups);
            players.forEach(player -> {
                player.getPlayerProxy().sendMsg(MessageManager.me().create(DungeonBO.updateActivityDungeon, ProtoUnit.toByte(msg)));
            });
        }
    }

    /**
     * 获取开始和结束的活动副本
     */
    private Map<Integer,List<Integer>> getTimePointGroup(Date date){
        List<DungeonLevelGroupCfg> allCfg = DungeonLevelGroupCfgCache.me().getAll();
        Map<Integer,List<Integer>> result = Maps.newHashMap();
        allCfg.forEach(group->{
            int timePoint = TimeFrameChecker.getTimePoint(group,date);
            if (timePoint != TimeFrameChecker.TIME_POINT_NONE){
                List<Integer> list = result.computeIfAbsent(timePoint,k-> Lists.newArrayList());
                list.add(group.getId());
            }
        });
        return result;
    }

    /**
     * 刷新充值礼包购买记录
     */
    private void refreshRechargeRecord(Collection<Player> players,boolean isNewDay){
        if (isNewDay){
        	players.forEach(player->GameRechargeManager.resetGiftBagRecord(player));
        }
    }

    /**
     * 重置看板娘城市约会
     */
    private void refreshCityDating(Collection<Player> players, Date now, boolean isNewDay){
        if (isNewDay){
            players.forEach(player -> {
                RoleManager.me().resetCityTriggerCount(player,now);
                CityDatingTriggerManager.refreshCityDating(player, now);
            });
        }
    }
}
